; 利用7ch中断实现
;   清理屏幕
;   设置前景色
;   设置背景色
;   向上滚动一行
assume cs:code, ss: stack
stack segment stack

    db 32 dup(0)
stack ends

code segment

start:
    mov ax, stack

    mov ss, ax

    mov sp, 32

    call initReg

    call copyCommandToMemoey

    call setInt7ch

    mov al, 4

    mov bp, 0

    int 7ch

    mov ax, 4c00H

    int 21H

    ret

; 7ch 中断调用
copyStart:

    jmp functionExe
; OFFSET clearScreen + 7E00H - OFFSET copyStart ？why？
; 因为  OFFSET clearScreen 是在编译期间确定胡位置，执行程序后指令在7E00H处，
; 此时OFFSET clearScreen并不代表方法在内存中胡位置,
; OFFSET clearScreen - OFFSET copyStart 获取的是方法在内存中的偏移量，即方法开始胡位置
; 在加上当初复制到的地址7E00H 即得到了他的真实地址
;
arrayFunction dw OFFSET clearScreen + 7E00H - OFFSET copyStart
              dw OFFSET setPreColor + 7E00H - OFFSET copyStart
              dw OFFSET setBlackgroundColor + 7E00H - OFFSET copyStart
              dw OFFSET upRow + 7E00H - OFFSET copyStart

    ;call clearScreen
    ;call setPreColor

    ;call setBlackgroundColor
functionExe:

    mov bx, OFFSET arrayFunction + 7E00H - OFFSET copyStart

    call word ptr es:[bx]

    iret


; 设置景色
setCommonColor:

    push es

    call setEs

    mov cx, 2000

    mov di, 1
color:
    and es:[di], bl

    or es:[di], al

    add di, 2

    loop color

    pop es

    ret

setEs:

    mov dx, 0b800H

    mov es, dx

    ret

; 向上一行
upRow:

    push es

    push ds

    push dx
    call setEs

    mov dx, 0b800H

    mov ds, dx

    mov si, 160

    mov di, 0

    mov cx, 80*24

    cld
    rep movsw

    mov cx, 80

    mov dx, 0700H

    mov di,  160*24

row:
    mov es:[di], dx

    add di, 2

    loop row

    pop dx
    pop ds
    pop es

    ret

; 设置背景色
setBlackgroundColor:

    mov bl, 10001111B   ; 参数

    mov cl, 4

    shl al, cl
    
    call setCommonColor

    ret

setPreColor:
    
    mov bl, 11111000B   ; 参数

    call setCommonColor

    ret


clearScreen:

    push es

    call setEs

    mov di, 0

    mov cx, 2000

    mov dx, 0700H
clear:
    mov es:[di], dx

    add di, 2

    loop clear

    pop es

    ret

copyEnd:
    nop


setInt7ch:

    cli
    mov word ptr es:[7CH * 4], 7E00H

    mov es:[7CH * 4 + 2], es

    sti
    ret

copyCommandToMemoey:

    mov si, OFFSET copyStart

    mov di, 7E00H

    mov cx, OFFSET copyEnd -  OFFSET copyStart

    cld
    rep movsb

    ret

initReg:

    mov ax, 0

    mov es, ax

    mov ax, cs

    mov ds, ax

    mov ax, 0

    ret
code ends

end start